package com.xinqi.modules.course.clazz.service.impl;

import cn.hutool.core.util.DesensitizedUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xinqi.common.base.enums.YesNoEnum;
import com.xinqi.common.base.enums.YesNoNumberEnum;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.user.Account;
import com.xinqi.common.base.utils.spring.Spring;
import com.xinqi.common.core.enums.StudentOperateGroup;
import com.xinqi.common.mybatis.data.service.impl.BaseServiceImpl;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.common.mybatis.utils.Queries;
import com.xinqi.common.satoken.utils.LoginHelper;
import com.xinqi.modules.course.clazz.convert.ClassGroupConvert;
import com.xinqi.modules.course.clazz.convert.ClassGroupStudentConvert;
import com.xinqi.modules.course.clazz.domain.ClassGroupEntity;
import com.xinqi.modules.course.clazz.domain.ClassGroupStudentEntity;
import com.xinqi.modules.course.clazz.domain.ClassParentGroupStudentEntity;
import com.xinqi.modules.course.clazz.domain.ClassStudentEntity;
import com.xinqi.modules.course.clazz.dto.req.*;
import com.xinqi.modules.course.clazz.dto.rsp.ClassGroupResultDTO;
import com.xinqi.modules.course.clazz.dto.rsp.ClassGroupStudentResultDTO;
import com.xinqi.modules.course.clazz.dto.rsp.ClassParentGroupStudentResultDTO;
import com.xinqi.modules.course.clazz.dto.rsp.ClassStudentResultDTO;
import com.xinqi.modules.course.clazz.mapper.ClassGroupMapper;
import com.xinqi.modules.course.clazz.mapper.ClassGroupStudentMapper;
import com.xinqi.modules.course.clazz.service.*;
import com.xinqi.modules.course.course.enums.group.GroupCreatedTypeEnum;
import com.xinqi.modules.homework.homework.client.CourseHomeworkClient;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 班级分组人员表服务层实现
 *
 * @author: system
 * @date: 2023/01/17
 */
@Service("classGroupStudentService")
@RequiredArgsConstructor
public class ClassGroupStudentServiceImpl extends BaseServiceImpl<ClassGroupStudentMapper, ClassGroupStudentEntity> implements ClassGroupStudentService {

    private final ClassGroupStudentConvert classGroupStudentConvert;
    @Lazy
    private final ClassGroupService classGroupService;
    private final ClassGroupConvert classGroupConvert;
    private final ClassParentGroupStudentService classParentGroupStudentService;
    @Lazy
    private final ChatRemindSyncService chatRemindSyncService;

    @Lazy
    private final ClassStudentService classStudentService;

    private final ClassGroupMapper classGroupMapper;

    private final CourseHomeworkClient homeworkClient;

    /**
     * 分页查询 班级分组人员表数据
     */
    @Override
    @DS("slaver")
    public PageInfo<ClassGroupStudentResultDTO> page(Param pageable, ClassGroupStudentQueryDTO query) {
        PageInfo<ClassGroupStudentResultDTO> pages = Pages.convert(baseMapper.findStudentPageList(Pages.page(pageable), query));
        if (CollectionUtils.isNotEmpty(pages.getRows())) {
            Long classId = pages.getRows().get(0).getClassId();

            // 获取主学生信息 没有 则未老师和助教直接获取操作用户ID
            ClassStudentResultDTO classMasterStudent = classStudentService.findVirtualClassStudentByClassIdAndUserId(classId, LoginHelper.getUserId());
            Long studentId = Objects.isNull(classMasterStudent) ? LoginHelper.getUserId() : classMasterStudent.getStudentId();

            ClassStudentResultDTO studentResultDTO = classStudentService.findAllRolesStudentByClassIdAndStudentId(classId, studentId);

            //设置手机号隐藏
            if (Objects.nonNull(studentResultDTO) && Objects.equals(studentResultDTO.getIsTeacher(), YesNoEnum.NO.ordinal())) {
                for (ClassGroupStudentResultDTO result : pages.getRows()) {
                    if (!Objects.equals(studentId, result.getStudentId())) {
                        // 学生查询不等于 查看用户主学生ID 隐藏手机号
                        result.setMobile(DesensitizedUtil.mobilePhone(result.getMobile()));
                    } else {
                        // 学生查询等于 查看用户学生ID 可以编辑
                        result.setIsEdit(YesNoNumberEnum.YES.getCode());
                    }
                }
            }
        }

        return pages;
    }

    /**
     * 查询 班级分组人员表数据
     */
    @Override
    public List<ClassGroupStudentResultDTO> find(ClassGroupStudentQueryDTO query) {
        return list(wrapper(query)).stream().map(classGroupStudentConvert::convert).collect(Collectors.toList());
    }

    private LambdaQueryWrapper<ClassGroupStudentEntity> wrapper(ClassGroupStudentQueryDTO query) {
        LambdaQueryWrapper<ClassGroupStudentEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(ClassGroupStudentEntity::getId, v));
        Queries.accept(query.getCourseId(), v -> wrapper.eq(ClassGroupStudentEntity::getCourseId, v));
        Queries.accept(query.getClassId(), v -> wrapper.eq(ClassGroupStudentEntity::getClassId, v));
        Queries.accept(query.getGroupId(), v -> wrapper.eq(ClassGroupStudentEntity::getGroupId, v));
        Queries.accept(query.getStudentId(), v -> wrapper.eq(ClassGroupStudentEntity::getStudentId, v));
        return wrapper;
    }

    /**
     * 根据id查询 班级分组人员表数据
     */
    @Override
    public ClassGroupStudentResultDTO findById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return Optional.ofNullable(baseMapper.selectById(id)).map(classGroupStudentConvert::convert).orElse(null);
    }

    /**
     * 新增 班级分组人员表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insert(ClassGroupStudentCreateDTO dto) {
        ClassGroupResultDTO group2 = Optional.ofNullable(classGroupService.findById(dto.getGroupId())).orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("分组不存在"));
        boolean exist = checkDuplicate(group2.getClassId(), dto.getGroupId(), dto.getStudentId());
        CommonErrors.BAD_REQUEST.check(!exist, "已是该小组成员");

        dto.setCourseId(group2.getCourseId());
        ClassGroupStudentEntity entity = classGroupStudentConvert.create(dto);
        try {
            ClassParentGroupStudentEntity parentGroupStudent = new ClassParentGroupStudentEntity();
            parentGroupStudent.setClassId(group2.getClassId());
            parentGroupStudent.setPid(group2.getPid());
            parentGroupStudent.setStudentId(dto.getStudentId());
            classParentGroupStudentService.save(parentGroupStudent);
            save(entity);
        } catch (DuplicateKeyException e) {
            throw CommonErrors.BAD_REQUEST.asException("学生已在分组中，请勿重复添加");
        }

        // 加入小组 -- 加入进行中小组作业
        homeworkClient.studentOperateGroup(dto.getClassId(), dto.getStudentId(), dto.getGroupId(),
            StudentOperateGroup.STUDENT_JOIN_GROUP);

        chatRemindSyncService.studentJoinGroup(LoginHelper.getNickname(), dto.getStudentId(), group2);
        return entity.getId();
    }

    /**
     * 根据id修改 班级分组人员表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(ClassGroupStudentUpdateDTO dto) {
        Optional.ofNullable(getById(dto.getId())).orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("数据不存在"));
        ClassGroupStudentEntity entity = classGroupStudentConvert.update(dto);
        return updateById(entity);
    }

    /**
     * 根据id删除 班级分组人员表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteByClassGroupStudentId(Account user, Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        ClassGroupStudentResultDTO old = Optional.ofNullable(findById(id)).orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("要删除的数据不存在"));
        ClassGroupResultDTO group2 = classGroupService.findById(old.getGroupId());
        //删除小组成员
        removeById(id);
        if (Objects.isNull(group2)) {
            return true;
        }
        //删除分组学生关系
        this.removePidStudent(old.getClassId(), group2.getPid(), old.getStudentId());
        List<ClassStudentResultDTO> relationStudentResultList = classStudentService.
            findRelationStudentByClassIdAndImitateStudentId(old.getClassId(), old.getStudentId());

        Spring.committed(() -> relationStudentResultList.forEach(relation -> chatRemindSyncService.studentQuitGroup(user.getNickname(), relation.getStudentId(), group2)));

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public void removePidStudent(Long classId, Long pid, Long studentId) {
        ClassParentGroupStudentQueryDTO queryDTO = new ClassParentGroupStudentQueryDTO();
        queryDTO.setClassId(classId);
        queryDTO.setPid(pid);
        queryDTO.setStudentId(studentId);
        List<ClassParentGroupStudentResultDTO> pidStudentList = classParentGroupStudentService.findList(queryDTO);
        if (CollectionUtils.isNotEmpty(pidStudentList)) {
            classParentGroupStudentService.removeBatchByIds(pidStudentList.stream().map(ClassParentGroupStudentResultDTO::getId).collect(Collectors.toList()));
        }

    }


    /**
     * 设置小组长：1.先查这个人是不是小组长，如果是小组长就取消组长；否则就设置小组长，
     * 设置小组长的时候需要查看组内其他成员是不是组长，如果有其他成员是组长，则取消掉该组长角色，把组长角色设置为这个人
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean setTeamLeader(ClassGroupStudentUpdateDTO dto) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getId()), "ID不能为空");

        ClassGroupStudentEntity old = Optional.ofNullable(getById(dto.getId())).orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("数据不存在"));
        ClassGroupResultDTO group2 = Optional.ofNullable(classGroupService.findById(old.getGroupId())).orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("分组不存在"));
        //取消小组的其他组长
        ClassGroupStudentEntity teamLeader = findByGroupIdAndIsGroupLeader(old.getGroupId(), YesNoEnum.YES.ordinal());
        if (!Objects.isNull(teamLeader)) {
            teamLeader.setIsGroupLeader(YesNoEnum.NO.ordinal());
            updateById(teamLeader);
        }
        //设置组长
        old.setIsGroupLeader(YesNoEnum.YES.ordinal());
        boolean flag = updateById(old);

        chatRemindSyncService.studentSetGroupTeamLeader(LoginHelper.getNickname(), old.getStudentId(), group2);

        return flag;
    }

    @Override
    public Boolean cancelTeamLeader(ClassGroupStudentUpdateDTO dto) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getId()), "ID不能为空");
        ClassGroupStudentEntity old = Optional.ofNullable(getById(dto.getId())).orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("数据不存在"));
        old.setIsGroupLeader(YesNoEnum.NO.ordinal());
        return updateById(old);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchUpdate(Long targetGroupId, Long sourceGroupId, List<ClassGroupStudentUpdateDTO> dtoList) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(sourceGroupId), "源分组id不能为空");
        ClassGroupResultDTO group2 = Optional.ofNullable(classGroupService.findById(targetGroupId)).orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("目标分组不存在"));

        CommonErrors.BAD_REQUEST.check(CollectionUtils.isNotEmpty(dtoList), "请选择要移动的学生");

        List<Long> idList = dtoList.stream().map(ClassGroupStudentUpdateDTO::getId).collect(Collectors.toList());
        CommonErrors.BAD_REQUEST.check(CollectionUtils.isNotEmpty(idList), "学生ID不能全为空");

        List<ClassGroupStudentEntity> entityList = findListByIds(idList);
        CommonErrors.BAD_REQUEST.check(CollectionUtils.isNotEmpty(entityList), "数据不存在");

        for (ClassGroupStudentEntity entity : entityList) {
            entity.setGroupId(targetGroupId);
            entity.setIsGroupLeader(YesNoEnum.NO.ordinal());
        }
        updateBatchById(entityList);

        List<Long> masterStudentIdList = entityList.stream().map(ClassGroupStudentEntity::getStudentId).collect(Collectors.toList());
        List<ClassStudentEntity> relationStudentList = classStudentService.findRelationStudentListByClassIdAndMasterIdList(group2.getClassId(), masterStudentIdList);

        Spring.committed(() -> chatRemindSyncService.studentBatchChangeGroup(LoginHelper.getNickname(), group2, relationStudentList));
        return true;
    }

    /**
     * 加入自由分组，这里只是单纯的加入。小组id
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean joinFreeTeam(ClassGroupStudentCreateDTO dto) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getPid()), "父分组id不能为空");
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getSign()), "小组口令不能为空");
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getStudentId()), "学生id不能为空");

        ClassGroupResultDTO parent = Optional.ofNullable(classGroupService.findById(dto.getPid())).orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("父分组不存在"));
        CommonErrors.BAD_REQUEST.check(System.currentTimeMillis() <= parent.getLastTime(), "已超过该分组设置的最后加入时间，无法加入分组");
        // 重新赋值班级ID
        dto.setClassId(parent.getClassId());

        ClassGroupSignQueryDTO query = new ClassGroupSignQueryDTO();
        query.setPid(dto.getPid());
        query.setSign(dto.getSign());
        ClassGroupResultDTO smallGroup = classGroupService.findByPidAndSign(query);
        if (Objects.isNull(smallGroup)) {
            //如果没有小组，创建小组
            ClassGroupEntity group = new ClassGroupEntity();
            group.setCourseId(parent.getCourseId());
            group.setClassId(parent.getClassId());
            group.setPid(dto.getPid());
            group.setType(GroupCreatedTypeEnum.FREEDOM.getCode());
            group.setName(dto.getSign() + "组");
            group.setSign(dto.getSign());
            group.setLastTime(parent.getLastTime());
            classGroupMapper.insert(group);
            smallGroup = classGroupConvert.convert(group);
        }

        //获取主学生信息
        ClassStudentResultDTO classMasterStudent = classStudentService.findVirtualClassStudentByClassIdAndUserId(dto.getClassId(), LoginHelper.getUserId());
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(classMasterStudent), "找不到对应的模拟用户，请确认用户已被移出？");

        CommonErrors.BAD_REQUEST.check(!checkDuplicate(dto.getClassId(), smallGroup.getId(), classMasterStudent.getStudentId()), "已是该小组成员");
        dto.setCourseId(smallGroup.getCourseId());
        dto.setClassId(smallGroup.getClassId());
        dto.setStudentId(classMasterStudent.getStudentId());
        ClassGroupStudentEntity student = classGroupStudentConvert.create(dto);
        student.setGroupId(smallGroup.getId());

        try {
            ClassParentGroupStudentEntity parentGroupStudent = new ClassParentGroupStudentEntity();
            parentGroupStudent.setClassId(smallGroup.getClassId());
            parentGroupStudent.setPid(smallGroup.getPid());
            parentGroupStudent.setStudentId(classMasterStudent.getStudentId());
            classParentGroupStudentService.save(parentGroupStudent);
            baseMapper.insert(student);
        } catch (DuplicateKeyException e) {
            throw CommonErrors.BAD_REQUEST.asException("学生已在分组中，请勿重复添加");
        }

        homeworkClient.studentOperateGroup(dto.getClassId(), LoginHelper.getUserId(), dto.getGroupId(),
            StudentOperateGroup.STUDENT_JOIN_GROUP);

        return true;
    }

    /**
     * 删除分组--同步删除分组下的小组成员
     *
     * @param groupIds    分组下小组
     * @param groupEntity 分组信息
     * @return
     */
    @Override
    public Boolean deleteByGroupId(List<Long> groupIds, ClassGroupEntity groupEntity) {

        //删除小组成员
        LambdaUpdateWrapper<ClassGroupStudentEntity> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(ClassGroupStudentEntity::getGroupId, groupIds);
        this.remove(wrapper);

        //删除分组学生关系
        LambdaUpdateWrapper<ClassParentGroupStudentEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(ClassParentGroupStudentEntity::getPid, groupEntity.getId()).eq(ClassParentGroupStudentEntity::getClassId, groupEntity.getClassId());
        classParentGroupStudentService.remove(updateWrapper);

        return true;
    }

    /**
     * 删除小组--同步删除小组成员
     *
     * @param groupId     小组ID
     * @param studentIds  学生ID集合
     * @param groupEntity 小组信息
     * @return
     */
    @Override
    public Boolean deleteByGroupId(Long groupId, List<Long> studentIds, ClassGroupEntity groupEntity) {
        //删除小组成员
        LambdaUpdateWrapper<ClassGroupStudentEntity> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(ClassGroupStudentEntity::getGroupId, groupId);
        this.remove(wrapper);

        //删除分组学生关系
        LambdaUpdateWrapper<ClassParentGroupStudentEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(ClassParentGroupStudentEntity::getStudentId, studentIds).eq(ClassParentGroupStudentEntity::getClassId, groupEntity.getClassId());
        classParentGroupStudentService.remove(updateWrapper);

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDelete(Account user, List<ClassGroupStudentDeleteDTO> dtoList) {
        CommonErrors.BAD_REQUEST.check(CollectionUtils.isNotEmpty(dtoList), "请选择要删除的学生");

        List<Long> idList = dtoList.stream().map(ClassGroupStudentDeleteDTO::getId).collect(Collectors.toList());
        CommonErrors.BAD_REQUEST.check(CollectionUtils.isNotEmpty(idList), "学生ID不能全为空");
        idList.forEach(id -> deleteByClassGroupStudentId(user, id));
        return true;
    }

    @Override
    public List<ClassGroupStudentResultDTO> findStudentList(ClassGroupStudentQueryDTO dto) {
        return baseMapper.findStudentList(dto);
    }

    @Override
    public List<ClassGroupStudentResultDTO> findStudentListByClassIdAndPid(Long classId, Long pid) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(classId), "班级id不能为空");
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(pid), "父分组ID不能为空");

        ClassGroupStudentQueryDTO dto = new ClassGroupStudentQueryDTO();
        dto.setClassId(classId);
        dto.setPid(pid);
        return baseMapper.findStudentList(dto);
    }

    @Override
    public ClassGroupStudentEntity findByGroupIdAndIsGroupLeader(Long groupId, Integer isLeader) {
        LambdaQueryWrapper<ClassGroupStudentEntity> wrapper = new LambdaQueryWrapper<>();
        Queries.accept(groupId, v -> wrapper.eq(ClassGroupStudentEntity::getGroupId, v));
        Queries.accept(isLeader, v -> wrapper.eq(ClassGroupStudentEntity::getIsGroupLeader, v));
        return getOne(wrapper);
    }

    @Override
    public List<ClassGroupStudentEntity> findListByGroupId(Long groupId) {
        LambdaQueryWrapper<ClassGroupStudentEntity> wrapper = new LambdaQueryWrapper<>();
        Queries.accept(groupId, v -> wrapper.eq(ClassGroupStudentEntity::getGroupId, v));
        return list(wrapper);
    }

    @Override
    public List<ClassGroupStudentEntity> findListByIds(List<Long> idList) {
        return baseMapper.selectBatchIds(idList);
    }

    @Override
    public List<ClassGroupStudentResultDTO> findListByCourseId(Long courseId) {
        ClassGroupStudentQueryDTO query = new ClassGroupStudentQueryDTO();
        query.setCourseId(courseId);

        return list(wrapper(query)).stream().map(classGroupStudentConvert::convert).collect(Collectors.toList());
    }

    /**
     * 批量添加组员
     *
     * @param list
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertBatch(List<ClassGroupStudentCreateDTO> list) {
        CommonErrors.BAD_REQUEST.check(CollectionUtils.isNotEmpty(list), "请选择要添加的学生");
        list.forEach(this::insert);
        return true;
    }

    /**
     * 系统随机分组 -- 保存数据
     *
     * @param list
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean randomSaveStudent(List<ClassGroupStudentCreateDTO> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            List<ClassGroupStudentEntity> entityList = new ArrayList<>();
            List<ClassParentGroupStudentEntity> studentEntityList = new ArrayList<>();
            list.stream().forEach(item -> {
                ClassGroupStudentEntity entity = classGroupStudentConvert.create(item);
                entityList.add(entity);

                ClassParentGroupStudentEntity parentGroupStudent = new ClassParentGroupStudentEntity();
                parentGroupStudent.setClassId(item.getClassId());
                parentGroupStudent.setPid(item.getPid());
                parentGroupStudent.setStudentId(item.getStudentId());
                studentEntityList.add(parentGroupStudent);
            });
            if (CollectionUtils.isNotEmpty(studentEntityList)) {
                this.classParentGroupStudentService.saveBatch(studentEntityList);
            }
            if (CollectionUtils.isNotEmpty(entityList)) {
                this.saveBatch(entityList);
            }
        }
        return true;
    }

    /**
     * 是否已存在
     *
     * @param classId   班级id
     * @param groupId   分组id
     * @param studentId 学生id
     * @return boolean
     */
    private boolean checkDuplicate(Long classId, Long groupId, Long studentId) {
        ClassGroupStudentQueryDTO query = new ClassGroupStudentQueryDTO();
        query.setClassId(classId);
        query.setGroupId(groupId);
        query.setStudentId(studentId);
        return baseMapper.exists(wrapper(query));
    }


    @Override
    public Integer findClassTotalStudentCount(Long classId) {
        return baseMapper.findClassTotalStudentCount(classId);
    }

    @Override
    public List<ClassGroupStudentResultDTO> findByPidAndSign(ClassGroupSignQueryDTO dto) {
        return baseMapper.findByPidAndSign(dto);
    }

    @Override
    public ClassGroupStudentResultDTO findByPidAndStudentId(Long id, Long userId) {
        return baseMapper.findByPidAndStudentId(id, userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer removeSelf(Long classGroupId) {

        // 获取主学生信息
        ClassGroupResultDTO classGroupResult = classGroupService.findById(classGroupId);
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(classGroupResult), "该小组不存在");
        ClassStudentResultDTO studentResult = classStudentService.findVirtualClassStudentByClassIdAndUserId(classGroupResult.getClassId(), LoginHelper.getUserId());
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(studentResult), "学生不存在");

        ClassGroupStudentResultDTO classGroupStudent = this.findByGroupAndStudentId(classGroupId, studentResult.getStudentId());
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(classGroupStudent), "该学生不在小组中");

        ClassGroupResultDTO group = Optional.ofNullable(classGroupService.findById(classGroupId)).orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("小组不存在"));
        //删除分组学生关系
        this.removePidStudent(group.getClassId(), group.getPid(), classGroupStudent.getStudentId());
        chatRemindSyncService.studentQuitGroup(LoginHelper.getNickname(), classGroupStudent.getStudentId(), group);
        //删除学生
        return baseMapper.deleteById(classGroupStudent.getId());
    }

    @Override
    public Map<Long, Integer> findInsideGroupStudentCountByGroups(Long classId, List<ClassGroupResultDTO> groupList) {
        return baseMapper.findInsideGroupStudentCountByGroups(classId, groupList);
    }

    @Override
    public List<ClassGroupStudentResultDTO> findStudentListByGroupIds(List<Long> groupIds) {
        CommonErrors.BAD_REQUEST.check(CollectionUtils.isNotEmpty(groupIds), "小组id不能为空");
        return baseMapper.findStudentListByGroupIds(groupIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteByClassIdAndStudentIdList(Account user, Long classId, List<Long> studentIdList) {
        LambdaQueryWrapper<ClassGroupStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ClassGroupStudentEntity::getClassId, classId);
        wrapper.in(ClassGroupStudentEntity::getStudentId, studentIdList);

        List<ClassGroupStudentEntity> studentList = list(wrapper);
        if (CollectionUtils.isNotEmpty(studentList)) {
            batchDelete(user, studentList.stream().map(classGroupStudentConvert::convertDel).collect(Collectors.toList()));
        }
        return true;
    }

    @Override
    public List<ClassGroupStudentEntity> findByClassIdList(List<Long> classIdList) {
        LambdaQueryWrapper<ClassGroupStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(ClassGroupStudentEntity::getClassId, classIdList);
        return list(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transferCourseClassGroupStudentList(Long newCourseId, List<ClassGroupStudentEntity> classGroupStudentList) {
        classGroupStudentList.forEach(s -> s.setCourseId(newCourseId));
        saveOrUpdateBatch(classGroupStudentList);
    }

    @Override
    public List<ClassGroupStudentEntity> findByClassIdAndStudentId(Long classId, Long studentId) {
        ClassGroupStudentQueryDTO query = new ClassGroupStudentQueryDTO();
        query.setClassId(classId);
        query.setStudentId(studentId);
        return list(wrapper(query));
    }

    private ClassGroupStudentResultDTO findByGroupAndStudentId(Long classGroupId, Long userId) {
        ClassGroupStudentQueryDTO queryDTO = new ClassGroupStudentQueryDTO();
        queryDTO.setGroupId(classGroupId);
        queryDTO.setStudentId(userId);

        return classGroupStudentConvert.convert(getOne(wrapper(queryDTO)));
    }

    /**
     * 批量添加分组学生信息
     */
    @Override
    public boolean saveAllBatch(List<ClassGroupStudentEntity> list) {
        return this.saveBatch(list);
    }

    /**
     * 校验学生是否已经在组里
     */
    @Override
    public List<ClassGroupStudentEntity> checkStudentInGroup(List<Long> groupIds, Long studentId) {
        LambdaQueryWrapper<ClassGroupStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ClassGroupStudentEntity::getStudentId, studentId);
        wrapper.in(ClassGroupStudentEntity::getGroupId, groupIds);
        return list(wrapper);
    }

}
